#include "common/system_log.h"
#include "pmi/ExchangeDimension.h"
#include "pmi/ExchangeGDT.h"
#include "pmi/ExchangePMIBase.h"
#include "pmi/ExchangePMIDatum.h"
#include "pmi/ExchangePMINote.h"
#include "pmi/ExchangePMINote.h"
#include "pmi/ExchangeRoughness.h"
#include "pmi/ExchangeShapePMIInfos.h"

#include <nlohmann/json.hpp>
#include "utils/json_util.h"

namespace  AMCAX::Exchange::Core::PMI {

std::string ExchangePMIBase::ToString(){
    nlohmann::json result ;
    result["name"] = GetName().empty()?"":GetName() ;
    result["id"] = GetId().empty()?"":GetId() ;
    result["isHide"] = GetIsHide()?"true":"false" ;
    return result.dump() ;
} ;

std::string ExchangePMIText::ToString(){
    nlohmann::json result ;
    result["upperText"] = GetUpperText().empty()?"":GetUpperText() ;
    result["lowerText"] =  GetLowerText().empty()?"":GetLowerText();
    result["beforeText"] = GetBeforeText().empty()?"":GetBeforeText();
    result["afterText"] =  GetAfterText().empty()?"":GetAfterText();
    result["prefixText"] =  GetPrefixText().empty()?"":GetPrefixText();
    result["suffixText"] = GetSuffixText().empty()?"":GetSuffixText(); 
    result["belowText"] =  GetBelowText().empty()?"":GetBelowText();

    return result.dump() ;    
} ;

std::string PMIZoneModifier::ToString()
{
    nlohmann::json result ;
    result["zoneModifierType"] = PMIToleranceModifierTypeToString(zoneModifierType) ;
    result["zoneModifierMagnitudeValue"] = zoneModifierMagnitudeValue ;
    return result.dump() ;
}

std::string PMIModifiedDatum::ToString(){
    nlohmann::json result = nlohmann::json::array();
    for (auto  z: zoneModifiers)
    {
        result.push_back(json_util::ToJson(z.ToString())) ;
    }
    return result.dump() ;
}

 std::string DatumRef::ToString(){
    nlohmann::json result ;
    if(!label.empty())
        result["label"] = label;
    result["text"] = json_util::ToJson(text.ToString()) ;//text.ToString();

    nlohmann::json datums = nlohmann::json::array() ;
    for(auto p : pmiModifierDatums){
        datums.push_back(json_util::ToJson(p.ToString())) ;
    }
    result["pmiModifierDatums"] = datums ;
    return result.dump() ;
}

std::string GDTRefFrame::ToString(){
    nlohmann::json result ;
    LOG_INFO("label: {}",label) ;
    if(!label.empty())
        result["label"] = label;

    nlohmann::json datums = nlohmann::json::array() ;
    for(auto p : datumRefs){
        if(!p){
            continue;
        }
        datums.push_back(json_util::ToJson(p->ToString())) ;
    }
    result["pmiModifierDatums"] = datums ;
    return result.dump() ;
}

std::string ExchangeGDTRow::ToString(){
    nlohmann::json result ;
    result["modifierType"] = PMIToleranceValueTypeToString(modifierType);
    result["toleranceMagnitudeValue"] =toleranceMagnitudeValue ;
    result["refinementToleranceValue"] =refinementToleranceValue ;
    result["rateUnit1"] =rateUnit1 ;
    result["rateUnit2"] =rateUnit2 ;

    nlohmann::json datums = nlohmann::json::array() ;
    for(auto p : zoneModifiers){
        datums.push_back(json_util::ToJson(p.ToString())) ;
    }
    result["zoneModifiers"] = datums ;
    if(gdtRefFrame)
        result["gdtRefFrame"] = json_util::ToJson(gdtRefFrame->ToString()) ; //gdtRefFrame->ToString() ;
    return result.dump() ;
}


std::string ExchangeGDT::ToString() {
    nlohmann::json result ;
    result["toleranceType"] = PMIToleranceTypeToString(toleranceType);
    result["valueType"] =PMIToleranceValueTypeToString(valueType) ;
    result["toleranceValue"] =toleranceValue ;
    result["refinementToleranceValue"] =refinementToleranceValue ;
    result["rateUnit1"] =rateUnit1 ;
    result["rateUnit2"] =rateUnit2 ;
    result["projectedToleranceLength"] =projectedToleranceLength ;
    result["profileShiftValue"] =profileShiftValue ;
    result["allAround"] =allAround?"true":"false" ;
    if(!note.empty())
        result["note"] =note ;
    result["noteText"] =json_util::ToJson(noteText.ToString()) ; //noteText.ToString() ;

    nlohmann::json datums = nlohmann::json::array() ;
    for(auto p : gdtRows){
        datums.push_back(json_util::ToJson(p.ToString())) ;
    }
    result["gdtRows"] = datums ;
    return result.dump() ;
}

std::string PMIExchangeDatum::ToString() {
    nlohmann::json result ;
    if(!label.empty())
        result["label"] = label;

    nlohmann::json datums = nlohmann::json::array() ;
    for(auto p : datumTargets){
        if(!p){
            continue;
        }
        datums.push_back(json_util::ToJson(p->ToString())) ;
    }
    result["datumTargets"] = datums ;
    return result.dump() ;
}


std::string ExchangeNote::ToString() {
    nlohmann::json result ;
    if(!noteType.empty())
        result["noteType"] = noteType;

    nlohmann::json noteTextArray = nlohmann::json::array() ;
    for(auto t : noteTexts){    
        nlohmann::json text  ;
        if(!t.label.empty())
            text["label"] =  t.label;
        if(!t.fontName.empty())
            text["fontName"] =  t.fontName;
        text["fontType"] =  PMIFontToString(t.fontType);
        text["fixedPitch"] =  t.fixedPitch?"true":"false";
        text["height"] =  t.height;
        text["bold"] =  t.bold?"true":"false";
        text["italic"] =  t.italic?"true":"false";
        text["underline"] =  t.underline?"true":"false";
        text["strikeThrough"] =  t.strikeThrough?"true":"false";
        text["overline"] =  t.overline?"true":"false";
        text["ratio"] =  t.ratio;
        text["slant"] =  t.slant;
        text["rgbaColor"] =  t.rgbaColor;
        noteTextArray.push_back(text) ;
    }
    result["noteTexts"] = noteTextArray ;
    result["isFlagNote"] = isFlagNote?"true":"false";
    result["isNOA"] = isNOA?"true":"false";
    return result.dump() ;
}

std::string ExchangeRoughness::ToString(){
    nlohmann::json result ;
    result["obtentionType"] = PMIRoughnessObtentionTypeToString(obtentionType);
    result["applicabilityType"] = PMIRoughnessApplicabilityTypeToString(applicabilityType);

    nlohmann::json datums = nlohmann::json::array() ;
    for(auto p : roughnessField){
        datums.push_back(p) ;
    }
    result["roughnessField"] = datums ;
    return result.dump() ;
}

std::string ExchangeShapePMIInfos::ToString(){
    nlohmann::json result ;


    nlohmann::json datums = nlohmann::json::array() ;
    for(auto p : pmiInfos){
        if(!p){
            continue;
        }
        datums.push_back(json_util::ToJson(p->ToString())) ;
    }
    result["pmiInfos"] = datums ;
    return result.dump() ;
}

std::string ExchangePMIDatumTarget::ToString()
{
    nlohmann::json result ;
    if(!label.empty())
        result["label"] =  label;
    result["targetType"] =  PMIDatumTargetTypeToString(targetType);
    if(!upperText.empty())
        result["upperText"] =  upperText;
    if(!lowerText.empty())
        result["lowerText"] =  lowerText;
    result["position1"] =  position1;
    result["position2"] =  position2;
    return result.dump() ;
}

std::string ExchangePMIDimension::ToString() 
{
    nlohmann::json result ;
    result["mainType"] = PMIDimensionMainTypeToString(GetMainType());
    result["subType"] = PMIDimensionSubTypeToString(GetSubType());
    result["calloutFeatureAnnotationType"] = PMICalloutFeatureAnnotationTypeToString(GetCalloutFeatureAnnotationType());
    result["dimensionValue"] = GetDimensionValue();
    result["unit"] = PMIUnitToString(GetUnit());
    result["coordValue"] = coordValue ;
    result["tolerancePrecisionValue"] = tolerancePrecisionValue;
    result["toleranceNumerialUpperValue"] = toleranceNumerialUpperValue;
    result["toleranceNumerialLowerValue"] = toleranceNumerialLowerValue;
    result["toleranceAlphanumericalUpperValue"] = toleranceAlphanumericalUpperValue;
    result["toleranceAlphanumericalLowerValue"] = toleranceAlphanumericalLowerValue;
    if(!prefixStr.empty())
        result["prefixStr"] = prefixStr;
    if(!suffixStr.empty())
        result["suffixStr"] = suffixStr;
    if(!beforeStr.empty())
        result["beforeStr"] = beforeStr;
    if(!afterStr.empty())
        result["afterStr"] = afterStr;
    if(!upperStr.empty())
        result["upperStr"] = upperStr;
    if(!holeCalloutDimText.empty())
        result["holeCalloutDimText"] = holeCalloutDimText;
    if(!belowStr.empty())
        result["belowStr"] = belowStr;
    result["numbericalFakeValue"] = numbericalFakeValue;
    result["alphanumericalFakeValue"] = alphanumericalFakeValue;
    result["isDriving"] = isDriving?"true":"false";
    result["note"] = json_util::ToJson(note.ToString()) ; //note.ToString();
    result["holeCalloutAlphanumericalValue"] = holeCalloutAlphanumericalValue;
    result["line2dStart"] = line2dStart;
    result["line2dEnd"] = line2dEnd;
    result["line2dSymbolStart"] = line2dSymbolStart;
    result["line2dSymbolEnd"] = PMIArrowSymbolToString(line2dSymbolEnd);
    result["line2dSymbolEnd"] = PMIArrowSymbolToString(line2dSymbolEnd);
    result["isSymbolOutside"] = isSymbolOutside?"true":"false";
    return result.dump() ;
}

}